#include "Model.h"

PNode Head = NULL;
PNode Tail = NULL;

PNode getHead()
{
    return Head;
}

void initModel()
{
    readData(&Head, &Tail);
}

void readData(PNode *head, PNode *tail)
{
    PNode current = *head;
    FILE *fp = fopen(PATH, "r");
    bool flag = false;
    if (fp != NULL)
    {
        char hc = fgetc(fp);
        if (hc != EOF)
        {
            fseek(fp, 0, SEEK_SET);
            while (!feof(fp))
            {
                linkNode(&current);
                if (!flag)
                {
                    flag = true;
                    *head = current;
                }
                fscanf(fp, "%llu$#$%lf$#$%[^\n]\n", &current->id, &current->money, current->name);
            }
            *tail = current;
        }
        fclose(fp);
    }
}

void writeData()
{
    FILE *fp = fopen(PATH, "w");
    for (PNode current = Head; current != NULL; current = current->next)
    {
        fprintf(fp, "%llu$#$%lf$#$%s\n", current->id, current->money, current->name);
    }
    fflush(fp);
    fclose(fp);
}

bool linkNode(PNode *node)
{
    PNode newNode = (PNode)malloc(sizeof(Node));
    if (newNode == NULL)
    {
        return false;
    }
    newNode->id = 0;
    memset(newNode->name, 0, N_NAME);
    newNode->next = NULL;

    if (*node != NULL)
    {
        (*node)->next = newNode;
    }
    else if (Head == NULL)
    {
        Head = newNode;
        Head->next = Tail;
    }
    *node = newNode;
    return true;
}

void freeData()
{
    for (PNode current = Head; current != NULL;)
    {
        PNode next = current->next;
        free(current);
        current = next;
    }
    Head = NULL;
}

PNode get(PNode node, uint64_t id)
{
    if (node == NULL || node->id == id)
    {
        return node;
    }
    else
    {
        return get(node->next, id);
    }
}

void set(PNode target, uint64_t id, char *name, double money)
{
    /*
     * 空指针：添加新的节点
     * 非空指针：修改当前节点的数据
     */
    if (target == NULL)
    {
        linkNode(&Tail);
        Tail->id = id;
        strcpy(Tail->name, name);
        Tail->money = money;
    }
    else
    {
        strcpy(target->name, name);
        target->money = money;
    }
}

bool delete(uint64_t id)
{
    PNode prior = NULL;
    PNode current = Head;
    while (current != NULL)
    {
        if (current->id == id)
        {
            if (prior != NULL)
            {
                PNode next = current->next;
                prior->next = next;
            }
            else
            {
                Head = current->next;
            }
            if (current->next == NULL)
            {
                Tail = prior;
            }
            free(current);
            return true;
        }
        prior = current;
        current = current->next;
    }
    return false;
}

void sort(Criteria crit)
{
    if (Head == NULL) return;
    PNode cur = Head;
    PNode cmp = cur->next;
    PNode priorCur = NULL;
    PNode priorCmp = cur;
    while (cur != NULL)
    {
        cmp = cur->next;
        priorCmp = cur;
        while (cmp != NULL)
        {
            if (compare(cur, cmp, crit))
            {
                PNode temp = cmp->next;
                //相邻节点交换
                if (cur->next == cmp)
                {
                    cmp->next = cur;
                    cur->next = temp;
                    priorCmp = cmp;
                }
                //非相邻节点交换
                else
                {
                    cmp->next = cur->next;
                    cur->next = temp;
                    priorCmp->next = cur;
                }
                if (priorCur == NULL)
                {
                    Head = cmp;
                }
                else
                {
                    priorCur->next = cmp;
                }
                if (temp == NULL)
                {
                    Tail = priorCmp->next;
                }
                temp = cur;
                cur = cmp;
                cmp = temp;
            }
            priorCmp = cmp;
            cmp = cmp->next;
        }
        priorCur = cur;
        cur = cur->next;
    }
}

bool compare(PNode current, PNode cmp, Criteria crit)
{
    //获得高2位，即比较对象准则
    Criteria obj = crit & 0b110;
    bool flag = false;
    switch (obj)
    {
    case CT_ID:
        if (current->id == cmp->id) return false;
        flag = current->id > cmp->id;
        break;
    case CT_NAME:
        if (strcmp(current->name, cmp->name) == 0) return false;
        flag = strcmp(current->name, cmp->name) > 0;
        break;
    case CT_MONEY:
        if (current->money == cmp->money) return false;
        flag = current->money > cmp->money;
        break;
    default:
        return false;
    }
    //获取低1位，即升降序准则
    return crit & 0b001 == CT_DESC ? !flag : flag;
}

void shutdownModel()
{
    freeData();
}